package com.yanqu.road.server.gameplayer.module.recharge;

import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.enums.eRechargeGainIndex;
import com.yanqu.road.entity.recharge.RechargeGain;
import com.yanqu.road.entity.recharge.RechargeMallTimes;
import com.yanqu.road.entity.recharge.RechargeMultipleInfo;
import com.yanqu.road.logic.bussiness.recharge.RechargeBussiness;
import com.yanqu.road.logic.pb.RechargePb;
import com.yanqu.road.pb.recharge.RechargeProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.manger.recharge.RechargeMgr;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.property.Property;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 充值增益状态
 */
public class RechargeGainModule extends GeneralModule {

	private Map<Integer, RechargeGain> rechargeGainMap;

	//mall  src
	private Map<Integer, Map<Integer, RechargeMallTimes>> rechargeTimesMap;

	public RechargeGainModule(GamePlayer player) {
		super(player);
	}

	@Override
	public boolean loadData() {
		rechargeGainMap = RechargeBussiness.getRechargeGainMap(player.getUserId());
		rechargeTimesMap = RechargeBussiness.getRechargeTimesMap(player.getUserId());

		try {
			moveOldData();
		}catch (Exception e){
			log.error(e.getMessage(), e);
		}
		return true;
	}

	private void moveOldData() {
		if(!RechargeMgr.isUseNewMultiple()){
			return;
		}
		//旧数据迁移
		for(RechargeGain rechargeGain : rechargeGainMap.values()){
			for (eRechargeGainIndex gainIndex : eRechargeGainIndex.values()) {
				if((rechargeGain.getState() & ((int) Math.pow(2, gainIndex.getValue()))) == 1) {
					RechargeMallTimes mallTimes = getRechargeMallTimes(rechargeGain.getMallId(), gainIndex.getValue());
					if (mallTimes == null) {
						mallTimes = new RechargeMallTimes();
						mallTimes.setUserId(player.getUserId());
						mallTimes.setMallId(rechargeGain.getMallId());
						mallTimes.setSrc(gainIndex.getValue());
						mallTimes.setTimes(1);
						mallTimes.setInsertOption();
						if(!rechargeTimesMap.containsKey(rechargeGain.getMallId())){
							rechargeTimesMap.put(rechargeGain.getMallId(), new ConcurrentHashMap<>());
						}
						rechargeTimesMap.get(rechargeGain.getMallId()).put(gainIndex.getValue(), mallTimes);
					}
				}
			}
		}
	}

	@Override
	public boolean afterLoadData() {
		return true;
	}

	@Override
	public boolean saveData() {
		if(null != rechargeGainMap) {
			for (RechargeGain info : rechargeGainMap.values()) {
				if (info.isInsertOption()) {
					RechargeBussiness.addRechargeGain(info);
				} else if (info.isUpdateOption()) {
					RechargeBussiness.updateRechargeGain(info);
				}
			}
		}
		if(RechargeMgr.isUseNewMultiple()) {
			if (null != rechargeTimesMap) {
				for (Map.Entry<Integer, Map<Integer, RechargeMallTimes>> mallEntry : rechargeTimesMap.entrySet()) {
					for (Map.Entry<Integer, RechargeMallTimes> srcEntry : mallEntry.getValue().entrySet()) {
						RechargeMallTimes times = srcEntry.getValue();
						if (times.isInsertOption()) {
							RechargeBussiness.addRechargeMallTimes(times);
						} else if (times.isUpdateOption()) {
							RechargeBussiness.updateRechargeMallTimes(times);
						}
					}
				}
			}
		}
		return true;
	}

	@Override
	public void afterLogin() {
		if(RechargeMgr.isUseNewMultiple()) {
			syncRechargeTimes(getRechargeMallTimesList(), Protocol.U_MALL_RECHARGE_TIMES_ALL_SYNC);
			syncRechargeConfig();
		}else {
			if(null != rechargeGainMap) {
				syncRechargeGain(new ArrayList<>(rechargeGainMap.values()));
			}
		}
	}

	private void syncRechargeGain(List<RechargeGain> rechargeGainList){
		if(null != rechargeGainList) {
			player.sendPacket(Protocol.U_MALL_RECHARGE_GAIN_SYNC, RechargePb.parseRechargeGainListMsg(rechargeGainList));
		}
	}

	private void syncRechargeGain(RechargeGain rechargeGain){
		if(null != rechargeGain) {
			List<RechargeGain> syncList = new ArrayList<>();
			syncList.add(rechargeGain);
			syncRechargeGain(syncList);
		}
	}

	public List<RechargeMallTimes> getRechargeMallTimesList(){
		List<RechargeMallTimes> list = new ArrayList<>();
		for (Map.Entry<Integer, Map<Integer, RechargeMallTimes>> mallEntry : rechargeTimesMap.entrySet()) {
			for (Map.Entry<Integer, RechargeMallTimes> srcEntry : mallEntry.getValue().entrySet()) {
				list.add(srcEntry.getValue());
			}
		}
		return list;
	}

	public Map<Integer, RechargeGain> getRechargeGainMap() {
		return rechargeGainMap;
	}

	public Map<Integer, Map<Integer, RechargeMallTimes>> getRechargeTimesMap() {
		return rechargeTimesMap;
	}

	/**
	 * 重置首充状态
	 */
	public void resetAll() {
		for (RechargeGain rechargeGain : rechargeGainMap.values()) {
			rechargeGain.setState(0);
		}
		if(RechargeMgr.isUseNewMultiple()) {
			for (Map.Entry<Integer, Map<Integer, RechargeMallTimes>> mallEntry : rechargeTimesMap.entrySet()) {
				for (Map.Entry<Integer, RechargeMallTimes> srcEntry : mallEntry.getValue().entrySet()) {
					srcEntry.getValue().setTimes(0);
				}
			}
			syncRechargeTimes(getRechargeMallTimesList(), Protocol.U_MALL_RECHARGE_TIMES_ALL_SYNC);
		}else {
			if(null != rechargeGainMap) {
				syncRechargeGain(new ArrayList<>(rechargeGainMap.values()));
			}
		}
	}

	/**
	 * 重置首充状态
	 */
	public void reset(int markIndex) {
		for (RechargeGain rechargeGain : rechargeGainMap.values()) {
			int value = (int) Math.pow(2, markIndex);
			int state = rechargeGain.getState() & ~value;
			rechargeGain.setState(state);
		}
		for (Map.Entry<Integer, Map<Integer, RechargeMallTimes>> mallEntry : rechargeTimesMap.entrySet()) {
			for(Map.Entry<Integer, RechargeMallTimes> srcEntry : mallEntry.getValue().entrySet()) {
				if(srcEntry.getValue().getSrc() == markIndex){
					srcEntry.getValue().setTimes(0);
				}
			}
		}
		syncRechargeTimes(getRechargeMallTimesList(), Protocol.U_MALL_RECHARGE_TIMES_ALL_SYNC);
	}

	/**
	 * 记录充值次数
	 */
	public void changeRechargeTimes(int mallId, int markIndex) {
		RechargeMallTimes mallTimes = getRechargeMallTimes(mallId, markIndex);
		if(mallTimes == null){
			mallTimes = new RechargeMallTimes();
			mallTimes.setUserId(player.getUserId());
			mallTimes.setMallId(mallId);
			mallTimes.setSrc(markIndex);
			mallTimes.setTimes(0);
			mallTimes.setInsertOption();
			if(!rechargeTimesMap.containsKey(mallId)){
				rechargeTimesMap.put(mallId, new ConcurrentHashMap<>());
			}
			rechargeTimesMap.get(mallId).put(markIndex, mallTimes);
		}
		mallTimes.setTimes(1 + mallTimes.getTimes());

		//同步给客户端
		syncRechargeTimes(mallTimes, Protocol.U_MALL_RECHARGE_TIMES_ONE_SYNC);
	}

	private void syncRechargeTimes(RechargeMallTimes mallTimes, int code) {
		if(null != mallTimes) {
			List<RechargeMallTimes> syncList = new ArrayList<>();
			syncList.add(mallTimes);
			syncRechargeTimes(syncList, code);
		}
	}

	private void syncRechargeTimes(List<RechargeMallTimes> syncList, int code){
		if(null != syncList) {
			player.sendPacket(code, RechargePb.parseRechargeTimesListMsg(syncList));
		}
	}

	private void syncRechargeConfig() {
		RechargeProto.RechargeMultipleConfigSyncMsg.Builder syncMsg = RechargeProto.RechargeMultipleConfigSyncMsg.newBuilder();
		for(RechargeMultipleInfo multipleInfo : RechargeMgr.getMultipleInfoList()){
			RechargeProto.RechargeMultipleConfigTemp.Builder builder = RechargeProto.RechargeMultipleConfigTemp.newBuilder();
			builder.setMallId(multipleInfo.getMallId());
			builder.addAllMultiple(multipleInfo.getMultipleList());
			syncMsg.addConfig(builder);
		}
		player.sendPacket(Protocol.U_MALL_RECHARGE_CONFIG_SYNC, syncMsg);
	}

	/**
	 * 修改充值增益状态
	 */
	public void changeRechargeGain(int mallId, int markIndex) {
		RechargeGain rechargeGain = rechargeGainMap.get(mallId);
		if(null == rechargeGain){
			rechargeGain = new RechargeGain();
			rechargeGain.setUserId(player.getUserId());
			rechargeGain.setMallId(mallId);
			rechargeGain.setState(0);
			rechargeGain.setInsertOption();
			rechargeGainMap.put(rechargeGain.getMallId(), rechargeGain);
		}
		rechargeGain.setState(rechargeGain.getState() | ((int) Math.pow(2, markIndex)));

		syncRechargeGain(rechargeGain);
	}

	public boolean isFirstRechargeDouble(MallInfo mallInfo, int markIndex){
		if(!mallInfo.isFirstDouble()){
			return false;
		}
		if(RechargeMgr.isUseNewMultiple()) {
			RechargeMallTimes mallTimes = getRechargeMallTimes(mallInfo.getMallId(), markIndex);
			if (mallTimes != null) {
				return mallTimes.getTimes() == 0;
			} else {
				return true;
			}
		}else {
			//判断首充翻倍标识位
			return !rechargeGainMap.containsKey(mallInfo.getMallId()) ||
					((rechargeGainMap.get(mallInfo.getMallId()).getState() & ((int) Math.pow(2, markIndex))) == 0);
		}
	}

	/**
	 * 处理充值返利倍数及记录充值次数
	 */
	public void handleRechargeMultiple(MallInfo mallInfo, Property resultProp, int markIndex) {
		if(mallInfo.isFirstDouble()){
			//判断充值倍数
			int multiple = getRechargeMultiple(mallInfo.getMallId(), markIndex);
			if (multiple > 1) {
				for(Map.Entry<Integer, BigInteger> dataEntry : resultProp.getGoods().entrySet()){
					dataEntry.setValue(dataEntry.getValue().multiply(BigInteger.valueOf(multiple)));
				}
			}
			changeRechargeTimes(mallInfo.getMallId(), markIndex);
		}
	}

	/**
	 * 计算本次充值的返利倍数
	 */
	public int getRechargeMultiple(int mallId, int markIndex){
		//已充值次数
		int hasTimes = 0;
		RechargeMallTimes mallTimes = getRechargeMallTimes(mallId, markIndex);
		if(mallTimes != null) {
			hasTimes = mallTimes.getTimes();
		}
		int multiple = 1;
		//充值倍数配置
		RechargeMultipleInfo multipleInfo = RechargeMgr.getMultipleInfoMap(mallId);
		if(multipleInfo != null){
			if(multipleInfo.getMultipleList().size() > hasTimes){
				return multipleInfo.getMultipleList().get(hasTimes);
			}
		}else if(hasTimes == 0){
			//无配置，默认首充2倍
			multiple = 2;
		}
		//正常
		return multiple;
	}

	/**
	 * 获取历史充值次数
	 */
	public RechargeMallTimes getRechargeMallTimes(int mallId, int src){
		if(rechargeTimesMap == null){
			return null;
		}
		if(!rechargeTimesMap.containsKey(mallId)){
			return null;
		}
		return rechargeTimesMap.get(mallId).get(src);
	}

}
